﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestByWire.Test
{
    [TestClass]
    public class UseAdditionalTestTargetAttributeTest
    {
        private UseAdditionalTestTargetAttribute _target;

        [TestInitialize]
        public void Init()
        {
            _target = new UseAdditionalTestTargetAttribute(typeof(IMyClass), typeof(MyClass));
        }
        [TestMethod]
        public void ImplementationTypeMustDeriveOrImplementInterfaceOfInterfaceTypeParameter()
        {
            Assert.IsNotNull(_target);
        }

        [TestMethod]
        public void ConstructorMustNotAcceptNullAsInterfaceType()
        {
            var exception = AssertEx.Throws<ArgumentNullException>(() => new UseAdditionalTestTargetAttribute(null, typeof(MyClass)));

            Assert.AreEqual("interfaceType", exception.ParamName);
        }

        [TestMethod]
        public void ConstructorMustNotAcceptNullAsImplementationType()
        {
            var exception = AssertEx.Throws<ArgumentNullException>(() => new UseAdditionalTestTargetAttribute(typeof(IMyClass), null));

            Assert.AreEqual("implementationType", exception.ParamName);
        }

        [TestMethod]
        public void ConstructorMustThrowExceptionIfProvidedInterfaceIsNotExposedOnImplementation()
        {
            var exception = AssertEx.Throws<InvalidOperationException>(() => new UseAdditionalTestTargetAttribute(typeof(IMyClass), typeof(LooseClass)));

            Assert.AreEqual("Interface type must be assignable from implementation type.", exception.Message);
        }

        [TestMethod]
        public void Inheritance()
        {
            Assert.IsInstanceOfType(_target, typeof(IContainerInteraction));
        }

        [TestMethod]
        public void TypeOnInteraction()
        {
            IContainerInteraction target = _target;
            Assert.AreEqual(typeof(IMyClass), target.RegistrationType);
            Assert.IsNull(target.RegistrationName);
        }
    }

    internal interface IMyClass
    {
    }

    internal class MyClass : IMyClass
    {
    }

    internal class LooseClass
    {
    }
}
